package app.hzvmap.com.rangecontrol.utils;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;

import java.util.HashMap;
import java.util.Set;

/**
 * Created by weiguo on 2017/10/17.
 */

public class AppSetting {

    // These settings are stored in SharedPreferences
    private static String SHARED_PREFERENCES_NAME = "app.hzvmap.com.rangecontrol"; //$NON-NLS-1$

    // / Settings variables
    private Application ctx;
    private SharedPreferences globalPreferences;
    private SharedPreferences defaultProfilePreferences;
    private SharedPreferences profilePreferences;

    private static HashMap<String, String> globalConfig = new HashMap<String, String>();

    private static AppSetting INSTANCE;

    public static AppSetting getAppSetting(Context ctx) {
        if (INSTANCE == null) {
            synchronized (ctx.getApplicationContext()) {
                if (INSTANCE == null) {
                    INSTANCE = new AppSetting(
                            (Application) ctx.getApplicationContext());
                }
            }
        }
        return INSTANCE;
    }

    public interface OsmandPreference<T> {
        T get();

        T get(boolean checkNull);

        boolean set(T obj);

        String getId();
    }

    private AppSetting(Application ctx) {
        this.ctx = ctx;
        profilePreferences = defaultProfilePreferences = globalPreferences = ctx
                .getSharedPreferences(SHARED_PREFERENCES_NAME,
                        Context.MODE_PRIVATE);
    }

    public static String getConfigValue(String key) {
        synchronized (globalConfig) {
            if (globalConfig != null && globalConfig.containsKey(key)) {
                return globalConfig.get(key);
            } else {
                return key;
            }
        }
    }

    public static boolean findConfigValue(String key) {
        synchronized (globalConfig) {
            if (globalConfig != null && globalConfig.containsKey(key)) {
                return true;
            } else {
                return false;
            }
        }
    }

    public static void putConfigValue(String key, String value) {
        synchronized (globalConfig) {
            if (!globalConfig.containsKey(key)) {
                globalConfig.put(key, value);
            } else {
                globalConfig.remove(key);
                globalConfig.put(key, value);
            }
        }
    }

    private SharedPreferences getProfilePreferences() {
        return ctx.getSharedPreferences(SHARED_PREFERENCES_NAME,
                Context.MODE_PRIVATE);
    }

    public abstract class CommonPreference<T> implements OsmandPreference<T> {
        private final String id;
        private final boolean global;
        private T cachedValue;
        private SharedPreferences cachedPreference;
        private boolean cache;
        private T defaultValue;

        public CommonPreference(String id, boolean global, T defaultValue) {
            this.id = id;
            this.global = global;
            this.defaultValue = defaultValue;
        }

        public CommonPreference(String id, boolean global, boolean cache,
                                T defaultValue) {
            this.id = id;
            this.global = global;
            this.cache = cache;
            this.defaultValue = defaultValue;
        }

        protected SharedPreferences getPreferences() {
            return global ? globalPreferences : profilePreferences;
        }

        protected T getDefaultValue() {
            if (global) {
                return defaultValue;
            }
            if (defaultProfilePreferences.contains(getId())) {
                return getValue(defaultProfilePreferences, defaultValue);
            } else {
                return defaultValue;
            }
        }

        protected abstract T getValue(SharedPreferences prefs, T defaultValue);

        protected abstract boolean setValue(SharedPreferences prefs, T val);

        @Override
        public T get() {
            if (cache && cachedValue != null
                    && cachedPreference == getPreferences()) {
                return cachedValue;
            }
            cachedPreference = getPreferences();
            cachedValue = getValue(cachedPreference, getDefaultValue());
            return cachedValue;
        }

        @Override
        public String getId() {
            return id;
        }

        @Override
        public boolean set(T obj) {
            SharedPreferences prefs = getPreferences();
            if (setValue(prefs, obj)) {
                cachedValue = obj;
                cachedPreference = prefs;
                return true;
            }
            return false;
        }

    }

    private class BooleanPreference extends CommonPreference<Boolean> {

        private BooleanPreference(String id, boolean defaultValue,
                                  boolean global) {
            super(id, global, defaultValue);
        }

        private BooleanPreference(String id, boolean defaultValue,
                                  boolean global, boolean cache) {
            super(id, global, cache);
        }

        @Override
        protected Boolean getValue(SharedPreferences prefs, Boolean defaultValue) {
            return prefs.getBoolean(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, Boolean val) {
            return prefs.edit().putBoolean(getId(), val).commit();
        }

        @Override
        public Boolean get(boolean checkNull) {
            return get();
        }
    }

    private class IntPreference extends CommonPreference<Integer> {

        private IntPreference(String id, int defaultValue, boolean global) {
            super(id, global, defaultValue);
        }

        private IntPreference(String id, int defaultValue, boolean global,
                              boolean cache) {
            super(id, global, cache, defaultValue);
        }

        @Override
        protected Integer getValue(SharedPreferences prefs, Integer defaultValue) {
            return prefs.getInt(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, Integer val) {
            return prefs.edit().putInt(getId(), val).commit();
        }

        @Override
        public Integer get(boolean checkNull) {
//            if (checkNull && get() == -1) {
//                LASTTIME.set("");
//                ACCOUNT.set("");
//                UPWD.set("");
//                USERNAME.set("");
//                USERID.set(-1);
//                GROUPNAME.set("");
//                Intent intent = new Intent(RFIDApp.getInstance().getTopActivity(), LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
//                RFIDApp.getInstance().getTopActivity().startActivity(intent);
//            }
            return get();
        }
    }

    private class LongPreference extends CommonPreference<Long> {

        private LongPreference(String id, Long defaultValue, boolean global) {
            super(id, global, defaultValue);
        }

        private LongPreference(String id, Long defaultValue, boolean global,
                               boolean cache) {
            super(id, global, cache, defaultValue);
        }

        @Override
        protected Long getValue(SharedPreferences prefs, Long defaultValue) {
            return prefs.getLong(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, Long val) {
            return prefs.edit().putLong(getId(), val).commit();
        }

        @Override
        public Long get(boolean checkNull) {
            return get();
        }
    }

    private class FloatPreference extends CommonPreference<Float> {

        private FloatPreference(String id, Float defaultValue, boolean global) {
            super(id, global, defaultValue);
        }

        private FloatPreference(String id, Float defaultValue, boolean global,
                                boolean cache) {
            super(id, global, cache, defaultValue);
        }

        @Override
        protected Float getValue(SharedPreferences prefs, Float defaultValue) {
            return prefs.getFloat(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, Float val) {
            return prefs.edit().putFloat(getId(), val).commit();
        }

        @Override
        public Float get(boolean checkNull) {
            return get();
        }
    }

    private class StringPreference extends CommonPreference<String> {

        private StringPreference(String id, String defaultValue, boolean global) {
            super(id, global, defaultValue);
        }

        @Override
        protected String getValue(SharedPreferences prefs, String defaultValue) {
            return prefs.getString(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, String val) {
            return prefs.edit().putString(getId(), val).commit();
        }

        @Override
        public String get(boolean checkNull) {
            return get();
        }
    }

    private class SetStringPreference extends CommonPreference<Set<String>> {

        private SetStringPreference(String id, Set<String> defaultValue, boolean global) {
            super(id, global, defaultValue);
        }

        @Override
        protected Set<String> getValue(SharedPreferences prefs, Set<String> defaultValue) {
            return prefs.getStringSet(getId(), defaultValue);
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, Set<String> val) {
            return prefs.edit().putStringSet(getId(), val).commit();
        }

        @Override
        public Set<String> get(boolean checkNull) {
            return get();
        }
    }

    private class EnumIntPreference<E extends Enum<E>> extends
            CommonPreference<E> {

        private final E[] values;

        private EnumIntPreference(String id, E defaultValue, boolean global,
                                  boolean cache, E[] values) {
            super(id, global, cache, defaultValue);
            this.values = values;
        }

        private EnumIntPreference(String id, E defaultValue, boolean global,
                                  E[] values) {
            super(id, global, defaultValue);
            this.values = values;
        }

        @Override
        protected E getValue(SharedPreferences prefs, E defaultValue) {
            int i = prefs.getInt(getId(), -1);
            if (i < 0 || i >= values.length) {
                return defaultValue;
            }
            return values[i];
        }

        @Override
        protected boolean setValue(SharedPreferences prefs, E val) {
            return prefs.edit().putInt(getId(), val.ordinal()).commit();
        }


        @Override
        public E get(boolean checkNull) {
            return get();
        }
    }


    public CommonPreference<String> ACCOUNT = new StringPreference("account",
            "", true);

    public CommonPreference<String> GUID = new StringPreference("guid",
            "14F5244858CD80", true);

    public CommonPreference<String> PARTNUM = new StringPreference("partnum",
            "14F5244858CD80", true);

    public CommonPreference<String> INSPECTDAY = new StringPreference("inspectday",
            "", true);

    public CommonPreference<Integer> PASSWORD = new IntPreference("password", -1,
            true);


    public CommonPreference<String> APPSERVER = new StringPreference(
            "appServer", "", true);

    public CommonPreference<String> APPLOGIN = new StringPreference(
            "appLogin", "", true);

    public CommonPreference<String> APPHOME = new StringPreference(
            "appHome", "", true);


    public CommonPreference<String> TRACKSERVER = new StringPreference(
            "trackServer", "", true);

    public CommonPreference<Integer> TRACKPORT = new IntPreference("trackPort", 0, true);

    public CommonPreference<Integer> RUNSTATE = new IntPreference("runstate", 0, true);


    public static String TEMP = "monitor_temp";
}
